package com.gateway.filter;

import com.example.common.constant.PlainToken;
import lombok.extern.slf4j.Slf4j;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.OAuth2Request;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.servlet.support.RequestContext;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.example.common.constant.Constant.*;

/**用于将 已解析的 Authorization 对象以明文的方式 放入请求中
 * 以便后端微服务直接使用，不用二次验证 token
 * @author 罗俊华
 * @date 2022/3/14 - 4:04 下午
 */
@Slf4j
public class SecurityContextConverterFilter implements GlobalFilter, Ordered {



    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {


        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if(!(authentication instanceof OAuth2Authentication)){
//            非 OAuth2 认证，拒绝
            return null;
        }

        OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) authentication;
//        获取当前用户的身份信息
        Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();

        String principal = userAuthentication.getName();

//        取出当前用户的权限信息
        List<String> authorizationList = userAuthentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList());

//        获取 OAuth2 请求信息
        OAuth2Request oAuth2Request = oAuth2Authentication.getOAuth2Request();

//        获取 request 的请求参数
        Map<String, String> requestParameters = oAuth2Request.getRequestParameters();

        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();


//        把请求参数、权限信息，身份都放在一起
        PlainToken jsonToken = new PlainToken(principal, authorizationList, requestParameters);



//      将明文权限和身份信息放入 请求头中，转发给其他微服务
        try {
            String jsonTokenString = new ObjectMapper().writeValueAsString(oAuth2Authentication);
            /*requestAttributes.setAttribute(
                    JSON_TOKEN,
                    jsonTokenString,
                    1);*/

            exchange.getRequest().getHeaders().add(JSON_TOKEN,jsonTokenString);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
